/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "FpsCommonGLMaterialRenderer.h"
//#include "CCommonGLDriver.h"
#include "EDriverFeatures.h"
//#include "EVertexAttributes.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if defined(_IRR_COMPILE_WITH_OPENGL_) || defined(_IRR_COMPILE_WITH_OPENGL_ES_) || defined(_IRR_COMPILE_WITH_PS3_)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

using namespace irr;
using namespace video;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ALPHA_TEST_NONTRANSPARENT::onSetMaterial(const SMaterial& material,
																				const SMaterial& lastMaterial,
																				bool resetAllRenderstates,
																				IMaterialRendererServices* services)
{
	Driver->disableTextures(1);
	Driver->setTexture(0, material.getTexture(0));
	Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

	if (material.getMaterialType() != lastMaterial.getMaterialType() || resetAllRenderstates)
	{
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.5f);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ALPHA_TEST_NONTRANSPARENT::onUnsetMaterial()
{
	glDisable(GL_ALPHA_TEST);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCommonGLMaterialRenderer_ALPHA_TEST_NONTRANSPARENT::isTransparent() const
{
	return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

u32 CCommonGLMaterialRenderer_ALPHA_TEST_NONTRANSPARENT::getVertexAttributeMask() const
{
	return EVA_POSITION | EVA_COLOR0 | EVA_TEXCOORD0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ADDITIVE_REPLACE_NONTRANSPARENT::onSetMaterial(const SMaterial& material,
																				const SMaterial& lastMaterial,
																				bool resetAllRenderstates,
																				IMaterialRendererServices* services)
{
	Driver->disableTextures(1);
	Driver->setTexture(0, material.getTexture(0));
	Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

	if (material.getMaterialType() != lastMaterial.getMaterialType() || resetAllRenderstates)
	{
		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
		Driver->setTexEnvMode(GL_REPLACE);
		glEnable(GL_BLEND);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ADDITIVE_REPLACE_NONTRANSPARENT::onUnsetMaterial()
{
	glDisable(GL_BLEND);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCommonGLMaterialRenderer_ADDITIVE_REPLACE_NONTRANSPARENT::isTransparent() const
{
	return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

u32 CCommonGLMaterialRenderer_ADDITIVE_REPLACE_NONTRANSPARENT::getVertexAttributeMask() const
{
	return EVA_POSITION | EVA_COLOR0 | EVA_TEXCOORD0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ADDITIVE_MODULATE_NONTRANSPARENT::onSetMaterial(const SMaterial& material,
																				const SMaterial& lastMaterial,
																				bool resetAllRenderstates,
																				IMaterialRendererServices* services)
{
	Driver->disableTextures(1);
	Driver->setTexture(0, material.getTexture(0));
	Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

	if (material.getMaterialType() != lastMaterial.getMaterialType() || resetAllRenderstates)
	{
		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
		Driver->setTexEnvMode(GL_MODULATE);
		glEnable(GL_BLEND);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_ADDITIVE_MODULATE_NONTRANSPARENT::onUnsetMaterial()
{
	glDisable(GL_BLEND);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCommonGLMaterialRenderer_ADDITIVE_MODULATE_NONTRANSPARENT::isTransparent() const
{
	return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

u32 CCommonGLMaterialRenderer_ADDITIVE_MODULATE_NONTRANSPARENT::getVertexAttributeMask() const
{
	return EVA_POSITION | EVA_COLOR0 | EVA_TEXCOORD0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_WITH_VERTEX_ALPHA::onSetMaterial(const SMaterial& material,
																							const SMaterial& lastMaterial,
																							bool resetAllRenderstates,
																							IMaterialRendererServices* services)
{
	Driver->disableTextures(1);
	Driver->setTexture(0, material.getTexture(0));
	Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

	if (material.getMaterialType() != lastMaterial.getMaterialType() || resetAllRenderstates
		|| material.getMaterialTypeParam(0) != lastMaterial.getMaterialTypeParam(0) )
	{
		Driver->setTexEnvMode(GL_COMBINE);
		Driver->setCombineRGB(GL_MODULATE);
		Driver->setSourceRGB(0, GL_TEXTURE);
		Driver->setSourceRGB(1, GL_PREVIOUS);

		Driver->setCombineAlpha(GL_MODULATE);
		Driver->setSourceAlpha(0, GL_TEXTURE);
		Driver->setSourceAlpha(1, GL_PRIMARY_COLOR);

		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);
		glEnable(GL_ALPHA_TEST);

		glAlphaFunc(GL_GREATER, material.getMaterialTypeParam(0));
	}
} 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_WITH_VERTEX_ALPHA::onUnsetMaterial()
{
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_BLEND);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CCommonGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_WITH_VERTEX_ALPHA::isTransparent() const
{
	return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

u32 CCommonGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_WITH_VERTEX_ALPHA::getVertexAttributeMask() const
{
	return EVA_POSITION | EVA_COLOR0 | EVA_TEXCOORD0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_LIGHTMAP_LIGHTING_ADD::onSetMaterial(const SMaterial& material,
													   const SMaterial& lastMaterial,
													   bool resetAllRenderstates,
													   IMaterialRendererServices* services)
{
	Driver->disableTextures(2);
	Driver->setTexture(1, material.getTexture(1));
	Driver->setTexture(0, material.getTexture(0));
	Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

	if (material.getMaterialType() != lastMaterial.getMaterialType() || resetAllRenderstates)
	{
		// diffuse map
		Driver->setTexEnvMode(GL_MODULATE);

		if (Driver->queryFeature(EVDF_MULTITEXTURE))
		{
			// lightmap
			Driver->activeTexture(GL_TEXTURE1);
			Driver->setTexEnvMode(GL_COMBINE);

			if (material.getMaterialType() == EMT_LIGHTMAP_LIGHTING_ADD)
				Driver->setCombineRGB(GL_ADD_SIGNED);
			else
				Driver->setCombineRGB(GL_SUBTRACT);

			Driver->setSourceRGB(0, GL_PREVIOUS);
			Driver->setSourceRGB(1, GL_TEXTURE);

			Driver->setCombineAlpha(GL_MODULATE);
			Driver->setSourceAlpha(0, GL_PREVIOUS);
			Driver->setSourceAlpha(1, GL_PREVIOUS);
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CCommonGLMaterialRenderer_LIGHTMAP_LIGHTING_ADD::onUnsetMaterial()
{
	if (Driver->queryFeature(EVDF_MULTITEXTURE))
	{
		Driver->activeTexture(GL_TEXTURE1);
		Driver->setTexEnvMode(GL_MODULATE);
		Driver->activeTexture(GL_TEXTURE0);
		Driver->setTexEnvMode(GL_MODULATE);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

u32 CCommonGLMaterialRenderer_LIGHTMAP_LIGHTING_ADD::getVertexAttributeMask() const
{
	return EVA_POSITION | EVA_COLOR0 | EVA_TEXCOORD0 | EVA_TEXCOORD1;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // _IRR_COMPILE_WITH_OPENGL_ || _IRR_COMPILE_WITH_OPENGL_ES_

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
